package com.gsbelarus.gedemin.lib.ui.activity;

import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.os.Build;
import android.os.Bundle;
import android.support.v4.app.FragmentManager;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.Toolbar;
import android.view.View;
import android.view.ViewGroup;
import android.view.WindowManager;
import android.widget.FrameLayout;

import com.afollestad.materialdialogs.GravityEnum;
import com.afollestad.materialdialogs.MaterialDialog;
import com.gsbelarus.gedemin.lib.R;
import com.gsbelarus.gedemin.lib.sync.protocol.SyncServiceModel;
import com.gsbelarus.gedemin.lib.sync.protocol.entity.SyncServiceStatus;
import com.gsbelarus.gedemin.lib.ui.ArgumentsHelper;
import com.gsbelarus.gedemin.lib.ui.dialog.DialogHelper;

abstract public class SyncActivityModel extends AppCompatActivity {

    protected Context context;
    protected ArgumentsHelper argumentsHelper;
    private BroadcastReceiver br;
    protected FragmentManager fragmentManager;
    protected MaterialDialog syncStatusDialog;
    protected Toolbar toolbar;

    protected boolean isActivityVisible;

    private int contentPaddingTop;

    /**
     * @return id View для отрисовки в активити
     */
    abstract public int getViewResource();


    public void onReceiveSyncStatus(SyncServiceStatus syncServiceStatus, SyncStatusDialog syncStatusDialog) {

    }

    /**
     * вызывается в методе onCreate(Bundle)
     *
     * @param arguments bundle с агрументами
     */
    public void onCreateActivity(Bundle arguments) {

    }

    /**
     * Если необходимо убрать toolbar, метод переопределяется в классе наследнике и возвращает false
     *
     * @return по умолчанию возвращает true
     */
    protected boolean isShowingToolbar() {
        return true;
    }

    @Override
    final protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.actvt);

        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP)
            getWindow().addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS);

        FrameLayout activityContent = (FrameLayout) findViewById(R.id.activity_content);
        activityContent.addView(getLayoutInflater().inflate(getViewResource(), activityContent, false), 0);
        contentPaddingTop = activityContent.getPaddingTop();

        showToolbar(activityContent);

        context = getBaseContext();
        fragmentManager = getSupportFragmentManager();
        argumentsHelper = new ArgumentsHelper();

        /** активность может запускать из других экранов или
         * восстанавливаться, если она была перед этим уничтожена ОС в случае нехватки памяти.
         * В первом случае берем данные из Intent,
         * во втором - сохраненные параметры из savedInstanceState */
        if (savedInstanceState == null) {
            argumentsHelper.readParams(getIntent());
        } else
            argumentsHelper.readParams(savedInstanceState);

        onCreateActivity(argumentsHelper.saveParams((savedInstanceState == null) ? new Bundle() : savedInstanceState));

        createBroadcastReceiver();
    }

    private void showToolbar(FrameLayout containerForShadow) {
        if (!isShowingToolbar()) {
            showContentPaddingTop(false);
            return;
        }

        FrameLayout actvt = (FrameLayout) findViewById(R.id.actvt);
        toolbar = (Toolbar) getLayoutInflater().inflate(R.layout.toolbar, actvt, false);
        actvt.addView(toolbar);
        findViewById(R.id.actvt_fits_system_windows).setFitsSystemWindows(true);

        setSupportActionBar(toolbar);

        View shadow = getLayoutInflater().inflate(R.layout.drop_shadow, containerForShadow, false);
        containerForShadow.addView(shadow);

        showElevationToolbar(true);
        showContentPaddingTop(true);
    }

    /**
     * Показать/скрыть тень от toolbar.
     * Для API < 21 используется view(drop_shadow) поверх контента
     * Для API >= 21 используется elevation на 10dp
     *
     * @param flag показывать или не показывать
     */
    public void showElevationToolbar(boolean flag) {
        float heightInDp = 4f;
        View shadow = findViewById(R.id.drop_shadow);
        if (Build.VERSION.SDK_INT < 21) {
            if (shadow != null) {
                shadow.setVisibility((flag) ? View.VISIBLE : View.GONE);
                ViewGroup.LayoutParams params = shadow.getLayoutParams();
                params.height = (int) (heightInDp * getResources().getDisplayMetrics().density);
                shadow.setLayoutParams(params);
            }

        } else {
            if (shadow != null)
                shadow.setVisibility(View.GONE);
            Toolbar toolbar = getToolbar();
            if (toolbar != null)
                toolbar.setElevation((flag) ? heightInDp * getResources().getDisplayMetrics().density : 0);
        }
    }

    /**
     * ловит и обрабатывает широковещательные сообщения от сервиса обновлений
     */
    private void createBroadcastReceiver() {
        br = new BroadcastReceiver() {
            @Override
            public void onReceive(Context context, Intent intent) {

                if (intent.getExtras().containsKey(SyncServiceStatus.class.getSimpleName())) {
                    SyncServiceStatus syncServiceStatus =
                            (SyncServiceStatus) intent.getExtras().getSerializable(SyncServiceStatus.class.getSimpleName());

                    if (syncServiceStatus.getTypeOfStatus() == SyncServiceStatus.TypeOfStatus.START_SYNC) {

                        if (syncStatusDialog != null)
                            syncStatusDialog.cancel();
                    }
                    onReceiveSyncStatus(syncServiceStatus, new SyncStatusDialog());
                }
            }
        };

        IntentFilter intFilt = new IntentFilter(SyncServiceModel.getBroadcastMessageAction(getApplicationContext()));

        registerReceiver(br, intFilt);
    }

    protected class SyncStatusDialog {

        public void show(SyncServiceStatus status) {
            /** если активити не видна или сообщение пустое, ничего не показываем */
            String message = status.getStatus().getMessage();
            if (!isActivityVisible || message == null || message.isEmpty())
                return;
            DialogHelper dialogHelper = new DialogHelper(SyncActivityModel.this);
            if (message.equals(getString(R.string.created_demo_db_text)))
                syncStatusDialog = dialogHelper.showMaterialDialog(null, message, GravityEnum.CENTER);
            else
                syncStatusDialog = dialogHelper.showMaterialDialog(getString(R.string.sync_status_notification), message, null);
        }
    }

    @Override
    protected void onPause() {
        super.onPause();
        setActivityVisible(false);
    }

    @Override
    protected void onResume() {
        super.onResume();
        setActivityVisible(true);
    }

    private void setActivityVisible(boolean flag) {
        isActivityVisible = flag;
        SyncServiceModel.isShowNotificationError = !flag;
        SyncServiceModel.isShowNotificationError = !flag;
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        if (syncStatusDialog != null)
            syncStatusDialog.cancel();
        unregisterReceiver(br);
    }

    /**
     * сохранение параметров, если процесс вдруг завершиться
     * при нехватке памяти или в каком-нибудь другом случае
     */
    @Override
    public void onSaveInstanceState(Bundle outState) {
        super.onSaveInstanceState(outState);
        argumentsHelper.saveParams(outState);
    }

    public void showContentPaddingTop(boolean flag) {
        FrameLayout content = (FrameLayout) findViewById(R.id.activity_content);
        if (content != null) {
            content.setPadding(
                    content.getPaddingLeft(),
                    flag ? contentPaddingTop : 0,
                    content.getPaddingRight(),
                    content.getPaddingBottom());
            content.invalidate();
        }
    }

    public Toolbar getToolbar() {
        return toolbar;
    }
}